import "./icon/iconfont.css"; // 引入阿里图标
import { FontMessage } from "./tools/Message";
// 头像截取插件
class Cut {
  // dom
  #fragment = document.createDocumentFragment() // 最大的文档碎片
  #body = document.body // body dom元素
  #dialog_box = null // 对话框 dom 对象
  #mask = null; // 灰色图层dom
  #close_dom = null // 关闭按钮
  #input = null // 选择文件的dom
  #dialog_footer = null // 对话框 底部容器
  #dialog_main = null // 对话框 展示图片区域容器
  #canvas = null // 画布
  #cut_canvas = null // 截图的画布
  #viewport = null // 截图窗口dom
  #draw_icon = null // 截图窗口右下角icon
  #draw_icon_down = null // 截图窗口右下角icon鼠标按下事件
  #draw_icon_move = null // 截图窗口右下角icon鼠标移动事件
  #draw_icon_up = null // 截图窗口右下角icon鼠标抬起事件
  #tips = null // 没上传文件得提示
  #input_button = null
  // 对象
  #img = null // 选择文件后创建的图片对象
  #ctx = null // canvas产生的对象
  #cut_canvas_ctx = null // 截图canvas对象
  #move = null
  #windowup = null // window鼠标抬起事件
  #viewportdown = null // 截图窗口按下事件
  #cutclick = null // 截图按钮点击事件
  // 窗口宽高 默认正方形 100 × 100
  #viewport_width = 100
  #viewport_height = 100
  #canvas_width = 0
  #canvas_height = 0
  #viewport_down_x = 0 // 截图视口按下的x位置
  #viewport_down_y = 0 // 截图视口按下的y位置
  #move_space_x = 0 // 截图窗口移动的距离
  #move_space_y = 0 // 截图窗口移动的距离
  // 系统参数
  #length = 0 // 选择文件的长度
  #movePosi_x = 0
  #movePosi_y = 0
  #draw_icon_down_x = 0 // 截图窗口右下角icon按下时的x
  #draw_icon_down_y = 0 // 截图窗口右下角icon按下时的y
  #max_x = 0 // 截图最大的边界距离
  #max_y = 0 // 截图最大的边界距离
  #type = 'blob' // 截图时返回的类型  base64 / file / blob    默认blob
  #last_x = 100
  #last_y = 100

  // 开始截取
  start(type = 'blob') {
    return new Promise(resolve => {
      if(document.getElementById('wjy-mask')) return
      let t = this
      // 如果类型传的不对 则给出提示，并设置默认值
      if(!['blob', 'file', 'base64'].includes(type)) {
        FontMessage({ type: "warning", message: `您传入的参数不是<b style='color: orange'> blob、base64、file </b>中的任意一个！我已经将其设置为 <b style='color: orange'> blob </b> 类型`, duration: 4000 });
        t.#type = 'blob'
      } else {
        t.#type = type
      }
      // 创建mask
      t.#create_mask(t, resolve)
      // 页面拉伸，清空内容
      window.addEventListener('resize', () => {
        if(!t.#img) return
        t.#ctx.clearRect(0, 0, t.#canvas_width, t.#canvas_height);
        t.#cut_canvas_ctx.clearRect(0, 0, t.#canvas_width, t.#canvas_height);
        t.#dialog_main. innerHTML = ''
        t.#input.value = ''
        t.#create_tips(t) // 重新创建提示
        t.#canvas = null
        t.#viewport = null
        t.#img = null
        t.#ctx = null
      })
    })
  }

  // 创建mask
  #create_mask(t, resolve) {
    t.#mask = document.createElement('div')
    t.#mask.id = 'wjy-mask'
    t.#mask.style.cssText = `
    width: 100vw;
    height: 100vh;
    position: fixed;
    left: 0;
    user-select: none;
    top: 0;
    background: rgba(0, 0, 0, .5);
    z-index: 999999;
    `
    t.#fragment.appendChild(t.#mask)
    // 创建对话框 dom 对象
    t.#create_dialog_box(t, resolve)
    // 创建关闭按钮
    t.#close(t)
  }

  // 关闭按钮
  #close(t) {
    t.#close_dom = document.createElement('div')
    t.#close_dom.id = 'wjy-close'
    t.#close_dom.innerHTML = '×'
    t.#close_dom.style.cssText = `
    position: fixed;
    right: 30px;
    top: 10px;
    color: #fff;
    cursor: pointer;
    font-size: 60px;
    z-index: 999999;
    `
    t.#mask.appendChild(t.#close_dom)
    t.#close_dom.addEventListener('click', () => {
      window.removeEventListener('mouseup', t.#windowup)
      t.#init_params(t)
    })
  }

  #init_params(t) {
    t.#body.removeChild(t.#mask)
    if(t.#tips) {
      t.#dialog_box.removeChild(t.#tips)
      t.#tips = null
    } 
    t.#dialog_box = null 
    t.#close_dom = null 
    t.#input = null 
    t.#dialog_footer = null 
    t.#dialog_main = null
    t.#canvas = null 
    t.#img = null 
    t.#ctx = null 
    t.#move = null
    t.#viewport_width = 100
    t.#viewport_height = 100
    t.#canvas_width = 0
    t.#canvas_height = 0
    t.#viewport_down_x = 0 // 截图视口按下的x位置
    t.#viewport_down_y = 0 // 截图视口按下的y位置
    t.#move_space_x = 0 // 截图窗口移动的距离
    t.#move_space_y = 0 // 截图窗口移动的距离
    t.#length = 0 // 选择文件的长度
    t.#mask = null; 
    t.#viewport = null 
    t.#input_button = null
  }

  // 创建对话框 dom 对象
  #create_dialog_box(t, resolve) {
    t.#dialog_box = document.createElement('div')
    t.#dialog_box.id = 'wjy-dialog'
    t.#dialog_box.style.cssText = `
    width: 80%;
    height: 80%;
    position: relative;
    padding: 10px 10px 0;
    box-sizing: border-box;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    background: #fff;
    z-index: 999999;
    box-shadow:  0px 0px 12px rgba(0, 0, 0, .12);
    border-radius: 5px;
    `
    t.#dialog_footer = document.createElement('div')
    t.#dialog_footer.id = 'wjy-dialog-footer'
    t.#dialog_footer.style.cssText = `
    width: 100%;
    height: 80px;
    position: relative;
    left: 0;
    box-sizing: border-box;
    bottom: 0;
    `

    t.#dialog_main = document.createElement('div')
    t.#dialog_main.id = 'wjy-dialog-main'
    t.#dialog_main.style.cssText = `
    width: 100%;
    height: calc(100% - 100px);
    position: relative;
    left: 0;
    top: 0;
    border-radius: 5px;
    border: 1px dashed #409eff;
    box-sizing: border-box;
    `

    t.#dialog_box.appendChild(t.#dialog_main)
    t.#dialog_box.appendChild(t.#dialog_footer)
    t.#mask.appendChild(t.#dialog_box)
    t.#body.appendChild(t.#fragment)
    t.#create_tips(t)
    t.#create_input(t, resolve)
  }

  // 截图按钮点击事件
  #cut_click(t, resolve) {
    if(!t.#ctx) {
      FontMessage({
        type: "warning",
        message: `<b style='color:orange'>您还没有选择图片!</b>`,
        duration: 2000,
      });
      return
    }
    
    // 获取截图区域的像素点信息
    let datas = t.#cut_canvas_ctx.getImageData(
      t.#viewport.getBoundingClientRect().left - t.#canvas.getBoundingClientRect().left,
      t.#viewport.getBoundingClientRect().top - t.#canvas.getBoundingClientRect().top,
      t.#viewport.offsetWidth,
      t.#viewport.offsetHeight
    );
    
    // 临时截取成功的canvas
    let temporary_canvas = document.createElement("canvas");
    temporary_canvas.id = 'temporary_canvas'
    temporary_canvas.width = t.#viewport.offsetWidth;
    temporary_canvas.height = t.#viewport.offsetHeight;
    let context = temporary_canvas.getContext("2d");
    context.putImageData(datas, 0, 0);
    if(t.#type === 'base64') {
      FontMessage({ type: "success", message: `<b style='color: #67c23a'>截取成功!</b>`, duration: 2000 });
      resolve(temporary_canvas.toDataURL("image/jpg", 1))
    } else if(t.#type === 'blob') {
      FontMessage({
        type: "success",
        message: `截取成功! 预览地址为：<b style='color: #67c23a'>${ window.URL.createObjectURL(t.#base64toFile(temporary_canvas.toDataURL("image/jpg", 1))) }</b>`,
        duration: 3500,
      });
      resolve(window.URL.createObjectURL(t.#base64toFile(temporary_canvas.toDataURL("image/jpg", 1))))
    } else if(t.#type === 'file') {
      FontMessage({ type: "success", message: `<b style='color: #67c23a'>截取成功!</b>`, duration: 2000 });
      resolve(new File([window.URL.createObjectURL(t.#base64toFile(temporary_canvas.toDataURL("image/jpg", 1)))], "head.jpg"))
    }
    temporary_canvas.remove(); // 删除调临时canvas
    t.#init_params(t)
  }

  // base64转文件流
  #base64toFile(dataurl, filename = "file") {
    let arr = dataurl.split(",");
    let mime = arr[0].match(/:(.*?);/)[1];
    let suffix = mime.split("/")[1];
    let bstr = atob(arr[1]);
    let n = bstr.length;
    let u8arr = new Uint8Array(n);
    while (n--) {
      u8arr[n] = bstr.charCodeAt(n);
    }
    return new File([u8arr], `${filename}.${suffix}`, {
      type: mime,
    });
  }

  // 创建没上传文件前的提示
  #create_tips(t) {
    if(t.#tips) return 
    t.#tips = document.createElement('div')
    t.#tips.id = 'wjy-file-tips'
    t.#tips.innerHTML = '请在下方选择要截取的图片'
    t.#tips.style.cssText = `
    position: absolute;
    letter-spacing: 1px;
    left: 50%;
    top: 50%;
    font-size: 16px;
    color: #409eff;
    font-weight: 1000;
    transform: translate(-50%, -50%);
    `
    t.#dialog_box.appendChild(t.#tips)
  }

  #create_input(t, resolve) {
    let input_wrap = document.createElement('div')
    input_wrap.id = 'wjy-file-wrap'
    input_wrap.style.cssText = `
    position: relative;
    top: 50%;
    width: 100%;  
    height: 70px;
    transform: translateY(-50%);
    `

    t.#input_button = document.createElement('div')
    t.#input_button.id = 'wjy-file-button'
    t.#input_button.innerHTML = '选择一张图片'
    t.#input_button.style.cssText = `
    position: absolute;
    width: 100%;
    height: 30px;
    background: #409eff;
    color: #fff;
    line-height: 30px;
    text-align: center;
    font-size: 14px;
    poniter-events: none;
    padding: 0 10px;
    border-radius: 4px;
    pointer-events: none;
    box-sizing: border-box;
    `

    let cut_button = document.createElement('div')
    cut_button.id = 'wjy-file-cut-button'
    cut_button.innerHTML = '截取'
    cut_button.style.cssText = `
    width: 100%;
    height: 30px;
    cursor: pointer;
    background: #67c23a;
    box-sizing: border-box;
    color: #fff;
    line-height: 30px;
    text-align: center;
    font-size: 14px;
    margin: 10px 0;
    padding: 0 10px;
    border-radius: 4px;
    `
    t.#cutclick = () => {
      t.#cut_click(t, resolve)
    }
    cut_button.addEventListener('click', t.#cutclick)
    
    t.#input = document.createElement('input')
    t.#input.id = 'wjy-file'
    t.#input.type = 'file'
    t.#input.accept = 'image/*'
    t.#input.style.cssText = `
    width: 100%;
    cursor: pointer;
    `
    t.#input.addEventListener('change', t.#changeFileFn)
    input_wrap.appendChild(cut_button)
    input_wrap.appendChild(t.#input_button)
    input_wrap.appendChild(t.#input)
    t.#dialog_footer.appendChild(input_wrap)
  }

  // 选择文件的事件处理函数
  #changeFileFn = (event) => {
    let t = this
    t.#length = event.target.files.length
    if(event.target.files.length === 0) return
    t.#input_button.innerHTML = '换一张图片'
    if(t.#img) t.#dialog_main.removeChild(t.#img)
    if(t.#tips) {
      t.#dialog_box.removeChild(t.#tips)
      t.#tips = null
    }
    t.#last_x = 100
    t.#last_y = 100
    t.#viewport_width = 100
    t.#viewport_height = 100
    t.#img = new Image()
    t.#img.src = URL.createObjectURL(event.target.files[0])
    t.#img.style.cssText = `
    object-fit: contain;
    position: absolute;
    left: 50%;
    top: 50%;
    visibility: hidden;
    transform: translate(-50%, -50%);
    z-index: -1;
    `
    t.#dialog_main.appendChild(t.#img)
    t.#img.addEventListener('load', (e) => {
      if(!t.#canvas) {
        t.#canvas = document.createElement('canvas')
        t.#canvas.id = 'wjy-canvas'
        t.#canvas.style.cssText = `
        width: 100%;
        height: 100%;
        `
        t.#ctx = t.#canvas.getContext("2d");
        // 截图画布
        t.#cut_canvas = document.createElement('canvas')
        t.#cut_canvas.id = 'wjy-cut-canvas'
        t.#cut_canvas.style.cssText = `
        width: 100%;
        position: absolute;
        left: 0;
        top: 0;
        height: 100%;
        z-index: -1;
        `
        t.#cut_canvas_ctx = t.#cut_canvas.getContext("2d");
      }
      
      t.#dialog_main.appendChild(t.#canvas)
      t.#dialog_main.appendChild(t.#cut_canvas)
      t.#canvas_width = t.#canvas.offsetWidth
      t.#canvas_height = t.#canvas.offsetHeight
      t.#movePosi_x = t.#canvas_width / 2 - 50
      t.#movePosi_y = t.#canvas_height / 2 - 50
      t.#max_x = t.#canvas_width +  t.#canvas.getBoundingClientRect().left
      t.#max_y = t.#canvas_height +  t.#canvas.getBoundingClientRect().top
      // 创建截图窗口
      t.#create_viewport(t)
      let img_width = e.target.offsetWidth
      let img_height = e.target.offsetHeight
      // 计算缩放比例
      let scale = Math.min(t.#canvas_width / img_width, t.#canvas_height / img_height);
      // 缩放后的宽度和高度
      t.#img.style.width = img_width * scale + 'px';
      t.#img.style.height = img_height * scale + 'px';
      let width = t.#img.style.width.split('px')[0] * 1
      let height = t.#img.style.height.split('px')[0] * 1
      // 设置canvas宽高
      t.#canvas.width = t.#canvas_width
      t.#canvas.height = t.#canvas_height
      t.#cut_canvas.width = t.#canvas_width
      t.#cut_canvas.height = t.#canvas_height
      // 设置图片在canvas上面居中
      let x = (t.#canvas_width - width) / 2
      let y = (t.#canvas_height - height) / 2
      t.#ctx.clearRect(0, 0, t.#canvas_width, t.#canvas_height);
      t.#ctx.drawImage(
        t.#img,
        x,
        y,
        width,
        height
      );
      // 设置图片在cut-canvas上面居中
      t.#cut_canvas_ctx.clearRect(0, 0, t.#canvas_width, t.#canvas_height);
      t.#cut_canvas_ctx.drawImage(
        t.#img,
        x,
        y,
        width,
        height
      );
      // 动态绘制canvas
      t.#paint(t, t.#canvas_width / 2 - 50, t.#canvas_height / 2 - 50, t.#viewport_width, t.#viewport_height)
    })
  }

  // 动态绘制canvas
  #paint(t, x, y, left, top) {
    t.#ctx.clearRect(0, 0, t.#canvas_width, t.#canvas_height);
    t.#ctx.globalCompositeOperation = "source-over";
    t.#ctx.fillStyle = "rgba(0, 0, 0, .6)";
    t.#ctx.fillRect(0, 0, t.#canvas_width, t.#canvas_height);
    t.#ctx.globalCompositeOperation = "destination-out";
    t.#ctx.fillRect(x, y, left, top);
  }

  // 截图窗口
  #create_viewport(t) {
    if(!t.#viewport) {
      t.#viewport = document.createElement('div')
      t.#viewport.id = 'wjy-viewport'
      t.#viewportdown = (e) => {
        document.removeEventListener('mousemove', t.#move)
        t.#viewport_down(e, t)
      }
      t.#viewport.addEventListener('mousedown', t.#viewportdown)
      t.#windowup = (e) => {
        if(t.#viewport_up) t.#viewport_up(e, t)
      }

      let viewport_inner = document.createElement('div')
      viewport_inner.id = 'wjy-viewport-inner'
      viewport_inner.style.cssText = `
      width: 100%;
      height: 100%;
      position: relative;
      `

      t.#draw_icon = document.createElement('div')
      t.#draw_icon.id = 'wjy-viewport-inner-icon'
      t.#draw_icon.setAttribute('class', 'iconfont icon-shurukuanglashen')
      t.#draw_icon.style.cssText = `
      width: 12px;
      height: 12px;
      position: absolute;
      right: 0;
      cursor: se-resize;
      bottom: 0;
      font-size: 10px;
      color: #fff;
      `
      t.#draw_icon_down = (e) => {
        e.stopPropagation(); // 阻止事件穿透
        t.#draw_icon_down_x = e.clientX
        t.#draw_icon_down_y = e.clientY
        document.addEventListener('mousemove', t.#draw_icon_move)
      }

      let x = 0
      let y = 0
      t.#draw_icon_move = (e) => {
        x = e.clientX  - t.#draw_icon_down_x
        y = e.clientY  - t.#draw_icon_down_y
        t.#last_x = t.#viewport_width + x
        t.#last_y = t.#viewport_height + y
        // 最小值 是100
        if (t.#last_x <= 100) t.#last_x = 100
        if (t.#last_y <= 100) t.#last_y = 100
        // 最大值不能超过 canvas的最大值
        if (t.#last_x + t.#viewport.getBoundingClientRect().left >= t.#max_x) t.#last_x = t.#max_x - t.#viewport.getBoundingClientRect().left
        if (t.#last_y + t.#viewport.getBoundingClientRect().top >= t.#max_y) t.#last_y = t.#max_y - t.#viewport.getBoundingClientRect().top

        t.#viewport.style.width = t.#last_x + 'px'
        t.#viewport.style.height = t.#last_y + 'px'
        t.#paint(t, t.#movePosi_x, t.#movePosi_y, t.#last_x, t.#last_y)
      }

      t.#draw_icon_up = (e) => {
        t.#viewport_width = t.#last_x
        t.#viewport_height = t.#last_y
        document.removeEventListener('mousemove', t.#draw_icon_move)
      }


      t.#draw_icon.addEventListener('mousedown', t.#draw_icon_down)
      document.addEventListener('mouseup', t.#draw_icon_up)

      window.addEventListener('mouseup', t.#windowup)
      viewport_inner.appendChild(t.#draw_icon)
      t.#viewport.appendChild(viewport_inner)
      t.#dialog_main.appendChild(t.#viewport)
    }

    t.#viewport.style.cssText = `
      width: ${ t.#viewport_width }px;
      height: ${ t.#viewport_height }px;
      position: absolute;
      left: calc(${t.#canvas_width / 2}px - ${t.#viewport_width / 2}px);
      top: calc(${t.#canvas_height / 2}px - ${t.#viewport_height / 2}px);
      cursor: move;
      border: 1px dashed #fff;
      z-index: 10;
      box-sizing: border-box;
      `
  }

  // 截图窗口鼠标按下事件
  #viewport_down(e, t) {
    t.#viewport_down_x = e.clientX
    t.#viewport_down_y = e.clientY
    t.#move_space_x = t.#viewport.getBoundingClientRect().left - t.#canvas.getBoundingClientRect().left
    t.#move_space_y = t.#viewport.getBoundingClientRect().top - t.#canvas.getBoundingClientRect().top
    t.#move = (e) => {
      t.#viewport_move(e, t)
    }
    document.addEventListener('mousemove', t.#move)
  }
  // 截图窗口鼠标移动事件
  #viewport_move(e, t) {
    let max_x = t.#canvas_width - t.#viewport_width;
    let max_y = t.#canvas_height - t.#viewport_height;
    t.#movePosi_x = t.#move_space_x + e.clientX - t.#viewport_down_x;
    t.#movePosi_y = t.#move_space_y + e.clientY - t.#viewport_down_y;
    // 边界判断
    if (t.#movePosi_x <= 0) {
      t.#movePosi_x = 0;
    }
    if (t.#movePosi_y <= 0) {
      t.#movePosi_y = 0;
    }
    if (t.#movePosi_x >= max_x) {
      t.#movePosi_x = max_x;
    }
    if (t.#movePosi_y >= max_y) {
      t.#movePosi_y = max_y;
    }

    t.#viewport.style.left = t.#movePosi_x + 'px'
    t.#viewport.style.top = t.#movePosi_y + 'px'
    t.#paint(t, t.#movePosi_x, t.#movePosi_y, t.#viewport_width, t.#viewport_height)
  }
  // 截图窗口鼠标抬起事件
  #viewport_up(e, t) {
    document.removeEventListener('mousemove', t.#move)
  }
}

export default new Cut()